/*
 * Copyright 2012 Walter Lütgenau.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package offset.nodes.client.model.component;

import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JApplet;
import offset.nodes.Constants;
import offset.nodes.client.chooser.model.GetPathFromUuid;
import offset.nodes.client.model.ServerModel;

/**
 * Creates an applet from the editing page of a node, i.e. the page with URL parameter "edit=true".
 * 
 * @author
 * Walter
 * Lütgenau
 */
public class ComponentEditorEnvironment {
    URL repository;
    URL dialog;
    String path;
    JApplet component;

    /**
     * Create a component editor from the uuid only
     * 
     * @param repository repository URL
     * @param dialog dialog URL
     * @param uuid the uuid of the node to be edited
     */
    public ComponentEditorEnvironment(URL repository, URL dialog, String uuid) {
        this.repository = repository;
        this.dialog = dialog;
        this.path = getNodePath(uuid);
    }
    
    /**
     * Create a component editor from the uuid plus a relative path.
     * 
     * @param repository repository URL
     * @param dialog dialog URL
     * @param uuid the uuid of the node to be edited
     * @param relativePath the relative path
     */
    public ComponentEditorEnvironment(URL repository, URL dialog, String uuid, String relativePath) {
        this.repository = repository;
        this.dialog = dialog;
        this.path = getNodePath(uuid) + Constants.PATH_SEPARATOR + relativePath;
    }    
    
    /**
     * Is this an editable page at all?
     * 
     * @return the decision
     */
    public boolean isEditablePage() {
        try {
            if (getPath() == null)
                return false;

            String appletPage = getAppletPage(repository, getPath());
            ComponentEditorParser appletParser = new ComponentEditorParser(appletPage);
            AppletInfo info = appletParser.getAppletInfo();
            if (info == null)
                return false;
            
            return true;
        } catch (Exception ex) {
            Logger.getLogger(ComponentEditorEnvironment.class.getName()).log(Level.SEVERE, null, ex);
            return false;
        }
        
    }
    
    /**
     * Init the editor.
     * 
     * Retrieve the text of the editing page. Parse the page and create an applet environment from the result.
     * Let the applet environment create the applet.
     */
    public void init() {
        try {
            if (getPath() == null)
                return;

            String appletPage = getAppletPage(repository, getPath());
            ComponentEditorParser appletParser = new ComponentEditorParser(appletPage);
            AppletInfo info = appletParser.getAppletInfo();
            if (info == null)
                return;

            AppletEnvironment appletEnvironment = new AppletEnvironment(info);
            this.component = appletEnvironment.getApplet();
            component.init();
            component.start();
        } catch (Exception ex) {
            ex.printStackTrace();
        }        
    }

    /**
     * Return the repository URL.
     * 
     * @return the repository URL
     */
    public URL getRepository() {
        return repository;
    }

    /**
     * Return the dialog services URL
     * 
     * @return the URL
     */
    public URL getDialog() {
        return dialog;
    }

    /**
     * Return the total path in the repository.
     * 
     * @return the total path
     */
    public String getPath() {
        return path;
    }

    /**
     * Return the created applet, associated to the artificial applet environment.
     * 
     * @return the applet
     */
    public JApplet getComponent() {
        return component;
    }
    
    /**
     * URL encode the path
     * 
     * @param value
     * @return 
     */
    protected String urlEncode(String value) {
        return value.replaceAll(" ", "\\+");
    }

    /**
     * Construct the URL to the subnode, request the corresponding HTML page in "edit" mode
     * from the repository and return it.
     *
     * @param documentBase
     * @param rootPath
     * @param relativePath
     * @param parameters
     * @return the page in "edit" mode.
     * @throws MalformedURLException
     * @throws IOException
     */
    protected String getAppletPage(URL base, String path) throws MalformedURLException, IOException {
        URL componentNode = new URL(base.getProtocol(), base.getHost(), base.getPort(), base.getPath() + path + Constants.PATH_SEPARATOR + getParameters());
        URLConnection connection = componentNode.openConnection();
        connection.connect();
        InputStream in = connection.getInputStream();
        byte[] buf = new byte[in.available()];
        in.read(buf);
        String response = new String(buf);

        return response;
    }

    /**
     * Request the path of the root node  from the server using the uuid.
     * 
     * @param uuid
     * @return
     */
    protected String getNodePath(String uuid) {
        if (uuid == null)
            return null;
        
        GetPathFromUuid.Request request = new GetPathFromUuid.Request();
        request.setUuid(uuid);
        GetPathFromUuid.Response response;
        try {
            response = (GetPathFromUuid.Response) send(this.dialog, request);
        } catch (Exception ex) {
            ex.printStackTrace();
            return null;
        }

        return urlEncode(response.getPath());
    }

    /**
     * Send a request to the server.
     * 
     * @param request
     * @return
     * @throws Exception
     */
    protected Serializable send(URL server, Serializable request) throws Exception {
        ServerModel serverModel = new ServerModel(server);
        return serverModel.sendRequest(request);
    }

    /**
     * Add parameters for editing.
     * 
     * @return
     */
    protected String getParameters() {
        String parameters = "?" + Constants.PARVALUE_EDIT + "=true";
        if (ServerModel.getAuthenticationParameters() != null)
            parameters = parameters + "&" + ServerModel.getAuthenticationParameters();

        return parameters;
    }
    
}
